<template>
  <el-input v-show="false" v-model="comFileIds"></el-input>
  <div class="upload-new" :class="showUploadIcon ? 'showAdd' : 'hideAdd'">
    <div class="upload-rules" v-if="!props.disabled">
      支持文件格式：{{
        props.allowUploadTypes.join('、')
      }}；单个文件大小不能超过{{ props.fileSize }}M；最多上传{{
        props.limit
      }}个文件
    </div>
    <el-upload
      v-model:file-list="comFileList"
      :data="{ bizType: props.bizType }"
      action="/api/file/uploadMaterials"
      :headers="headers"
      list-type="picture-card"
      :on-success="uploadSuccess"
      :on-preview="handlePreviewFile"
      :on-progress="onUploadProgress"
      :limit="props.limit"
      v-bind="$attrs"
      :before-upload="beforeUpload"
      :multiple="true"
    >
      <template #file="{ file }">
        <div class="file-item-content wh-full flex items-center justify-center">
          <div
            v-loading="file.status != 'success'"
            class="wh-full"
            v-if="renderFileType(file.extension) === 'img'"
          >
            <div
              class="wh-full"
              :class="
                props.showImgPreview ? 'file-shadow' : 'file-shadow-false'
              "
            >
              <el-icon
                v-if="props.showImgPreview"
                size="25"
                class="preview-icon"
                @click="handlePreviewFile(file)"
              >
                <ZoomIn />
              </el-icon>
              <el-icon
                v-if="!props.disabled"
                size="25"
                class="preview-icon ml-10px"
                @click="removeFile(file, comFileList)"
              >
                <Delete />
              </el-icon>
            </div>
            <el-image class="wh-full" :src="file.url" fit="fill"></el-image>
          </div>
          <div
            v-loading="file.status != 'success'"
            class="wh-full flex items-center justify-center flex-col"
            v-else
          >
            <div class="file-shadow wh-full">
              <el-icon
                v-if="file.extension === 'pdf'"
                size="25"
                class="preview-icon"
                @click="viewPdf(file)"
              >
                <View />
              </el-icon>
              <el-icon size="25" class="preview-icon" @click="downFile(file)">
                <Download />
              </el-icon>
              <el-icon
                v-if="!props.disabled"
                size="25"
                class="preview-icon ml-10px"
                @click="removeFile(file, comFileList)"
              >
                <Delete />
              </el-icon>
            </div>
            <div class="w-60px mt-10px">
              <el-image :src="renderFileType(file.extension)"></el-image>
            </div>
            <div class="text-12px text-truncate w-full px-10px text-center">
              {{ file.name }}
            </div>
          </div>
        </div>
      </template>
      <!-- <div v-if="useUserStore().getParams('OPEN_OFF_GAO') == '1'" class="custom-btn">
        <el-button>本地上传</el-button>
        <el-button v-if="useUserStore().getParams('OPEN_OFF_GAO') == '1'" @click="takeImg($event)">
          高拍仪上传
        </el-button>
      </div> -->
      <el-icon>
        <Plus />
      </el-icon>
    </el-upload>
    <pub-dialog
      v-if="dialogVisible_high"
      title="高拍仪"
      :hasExtraBtn="true"
      v-model:visible="dialogVisible_high"
      width="1000px"
      @close="high_camera.closeWebsocket()"
    >
      <high-camera ref="high_camera" @pushFileList="pushFileList" @close="closeDialog"></high-camera>
    </pub-dialog>
  </div>
  <el-image-viewer
    v-if="showPreviewer"
    :url-list="previewList"
    :initial-index="previewIndex"
    teleported
    @close="closePreview"
  />
</template>
<script setup>
import {
  Loading,
  Plus,
  ZoomIn,
  Delete,
  Download,
  View
} from '@element-plus/icons-vue'
import { computedAsync, useVModel, watchIgnorable } from '@vueuse/core'
import { get_base64_file, upload_file } from '@/api/api'
import { useUserStore } from '@/pinia/modules/user'
import { ElMessageBox, ElMessage } from 'element-plus'
import { intersection } from 'lodash-es'
import { onBeforeMount } from 'vue'
import doc from './img/doc.png'
import excel from './img/excel.png'
import pdf from './img/pdf.png'
import zip from './img/zip.png'
import highCamera from './high-camera.vue'

const userStore = useUserStore()
const props = defineProps({
  bizType: {
    type: String,
    required: false,
    default: ''
  },
  fileIds: {
    type: String,
    default: ''
  },
  disabled: {
    type: Boolean,
    default: false
  },
  fileSize: {
    type: Number,
    default: 8
  },
  allowUploadTypes: {
    type: Array,
    default: () => ['jpg', 'jpeg', 'png', 'doc', 'docx', 'pdf', 'xlsx', 'xls']
  },
  limit: {
    type: Number,
    default: 10
  },
  showImgPreview: {
    type: Boolean,
    default: true
  }
})
const headers = ref({
  Authorization: userStore.token
})

const emit = defineEmits(['update:fileIds', 'uploading'])
const attrs = useAttrs()
const comFileIds = useVModel(props, 'fileIds', emit)
// 初始化请求图片
const comFileList = ref([])


const dialogVisible_high = ref(false)
const high_camera = ref()
// 选择高拍仪
const takeImg = event => {
  event.stopPropagation()
  dialogVisible_high.value = true
}

const closeDialog = ()=>{
  high_camera.value.closeWebsocket()
  dialogVisible_high.value = false
}

// 高拍仪手动上传调用接口
const pushFileList = file => {
  emit('uploading', true)
  high_camera.value.closeWebsocket()
  dialogVisible_high.value = false
  let params = new FormData()
  params.append('file', file)
  params.append('bizType', props.bizType)
  upload_file(params).then(result => {
    if (result.succeed) {
       comFileList.value.push({
          name: result.data.name,
          url: `data:image/jpg;base64,${result.data.baseThumbnailUrl}`,
          id: result.data.id,
          selfId: result.data.id,
          extension: result.data.extension,
          base64: `data:image/jpg;base64,${result.data.baseThumbnailUrl}`
        })
        comFileIds.value = comFileIds.value
          ? `${comFileIds.value},${result.data.id}`
          : `${result.data.id}`
        stop()
        emit('uploading', false)
      
    }
  })
}
const initFiles = async () => {
  const fileIds = props.fileIds ? props.fileIds.trim().split(',') : []
  if (fileIds.length === 0) return
  // fileIds.forEach(async item => {
  //   await get_base64_file(item).then(res => {
  //     const { data, succeed } = res
  //     if (succeed) {
  //       comFileList.value.push({
  //         name: data.name,
  //         url: `data:image/jpg;base64,${data.baseThumbnailUrl}`,
  //         id: data.id,
  //         selfId: data.id,
  //         extension: data.extension,
  //         base64: `data:image/jpg;base64,${data.baseThumbnailUrl}`
  //       })
  //     }
  //   })
  // })
  fileIds.reduce(async (pre, next) => {
    await pre
    return get_base64_file(next).then(res => {
      const { data, succeed } = res
      if (succeed) {
        comFileList.value.push({
          name: data.name,
          url: `data:image/jpg;base64,${data.baseThumbnailUrl}`,
          id: data.id,
          selfId: data.id,
          extension: data.extension,
          base64: `data:image/jpg;base64,${data.baseThumbnailUrl}`
        })
      }
    })
  }, Promise.resolve())
}
// 初始化监测一次fileIds变化 请求图片
const { stop } = watchIgnorable(
  () => comFileIds.value,
  (newVal, oldVal) => {
    initFiles()
  },
  { immediate: true }
)

const showUploadIcon = computed(() => {
  if (props.disabled) {
    return false
  }
  if (comFileList.value.length >= props.limit) {
    return false
  }
  return true
})
//
const onUploadProgress = (event, file, fileList) => {
  console.log('上传中')
  emit('uploading', true)
}
// 上传成功
const uploadSuccess = (res, file, fileList) => {
  console.log('上传结束')
  emit('uploading', false)
  const { data, succeed, msg } = res
  if (succeed) {
    file.selfId = data.id
    file.extension = data.extension
    file.base64 = `data:image/jpg;base64,${data.baseUrl}`
    comFileIds.value = comFileIds.value
      ? `${comFileIds.value},${data.id}`
      : `${data.id}`
    stop()
  } else {
    ElMessage.error(msg)
    fileList.pop()
  }
}
// 删除附件
const removeFile = (file, fileList) => {
  const index = fileList.findIndex(item => item.selfId === file.selfId)
  if (index > -1) {
    fileList.splice(index, 1)
  }
  comFileIds.value = fileList.map(item => item.selfId).join(',')
  stop()
}
// 下载附件
const base64ToBlob = function (base64) {
  // base64编码格式：'...'
  const MIMEAndCode = base64.split(';base64,') // 分割完整的base64编码分别得到各个部分（MIME文件类型相关、纯编码）
  const contentType = MIMEAndCode[0].split(':')[1] // image/jpeg，用于构造Blob对象时指定文件类型type
  // Blob对象的第一个构造参数是BufferArray对象或者BufferArrayView对象或者Blob
  // BufferArray对象或者BufferArrayView对象的区别就是BufferArray就是纯二进制内容，不方便我们直接操作，BufferArrayView对象比如Uint8Array数组，就是把二进制内容变成方便我们操作的数据
  // 把纯base64编码转为解码后的字符串
  const rawCode = window.atob(MIMEAndCode[1])

  // 创建一个Uint8Array数组，长度为解码后字符的长度
  const rawCodeLength = rawCode.length
  const uInt8Array = new Uint8Array(rawCodeLength)
  // 遍历，把每个解码后的字符通过charCodeAt方法转为对应字符的Unicode编码（一种编码而已，值为0 - 65535 之间的整数）
  for (let i = 0; i < rawCodeLength; i++) {
    uInt8Array[i] = rawCode.charCodeAt(i)
  }
  // new Blob第一个参数为数组，数组里面是BufferArray或者BufferArrayView对象，第二个配置对象的type属性指定文件类型
  return new Blob([uInt8Array], {
    type: contentType
  })
}
const downFile = file => {
  const blob = base64ToBlob(file.base64) // 拿到base64编码对应的blob对象传给URL.createObjectURL方法，构建一个href值
  let a = document.createElement('a')
  a.href = URL.createObjectURL(blob)
  a.download = `${file.name}`
  a.click()
  a = null
}
// 预览图片
const showPreviewer = ref(false)
const previewIndex = ref(0)
// 筛选出仅是图片的数据
const previewListObj = computed(() => {
  let arr = []
  comFileList.value.forEach(item => {
    if (['jpg', 'jpeg', 'png'].includes(item.extension)) {
      arr.push({
        url: item.url,
        selfId: item.selfId
      })
    }
  })
  return arr
})
const previewList = computed(() => {
  return previewListObj.value.map(item => item.url)
})
const handlePreviewFile = async file => {
  console.log(previewList.value)
  previewIndex.value = previewListObj.value.findIndex(
    item => item.selfId === file.selfId
  )
  showPreviewer.value = true
}
const closePreview = () => {
  showPreviewer.value = false
}
// // 是否展示添加按钮
// const showAddIcon = computed(() => {
//   return comFileList.value.length >= attrs.limit || props.disabled
// })
// 查看pdf
const viewPdf = file => {
  const MIMEAndCode = file.base64.split(';base64,') // 分割完整的base64编码分别得到各个部分（MIME文件类型相关、纯编码）
  const path = MIMEAndCode[1]
  var binary_string = window.atob(path)
  var len = path.length
  var bytes = new Uint8Array(len)
  for (var i = 0; i < len; i++) {
    bytes[i] = binary_string.charCodeAt(i)
  }
  let blob = new Blob([bytes.buffer], { type: 'application/pdf' })
  var url = URL.createObjectURL(blob)
  window.open(url)
}
const beforeUpload = file => {
  if (props.allowUploadTypes.length > 0) {
    const fileType = file.name.replace(/.+\./, '')
    const isConformType = props.allowUploadTypes.indexOf(fileType) === -1
    if (isConformType) {
      ElMessage.error(`请上传${props.allowUploadTypes.join('，')}格式文件!`)
      return !isConformType
    }
  }
  const isConform = file.size / 1024 / 1024 > props.fileSize
  if (isConform) {
    ElMessage.error(`上传文件大小不能超过${props.fileSize}MB!`)
  }
  return !isConform
}

const renderFileType = extension => {
  switch (extension) {
    case 'doc':
      return doc
    case 'docx':
      return doc
    case 'pdf':
      return pdf
    case 'xlsx':
      return excel
    case 'xls':
      return excel
    case 'zip':
      return zip
    case 'rar':
      return zip
    default:
      return 'img'
  }
}

</script>
<style lang="scss" scoped>
.upload-new {
  position: relative;
  &.hideAdd {
    :deep(.el-upload--picture-card) {
      display: none;
    }
  }
  .file-item-content {
    &:hover {
      .file-shadow {
        opacity: 0.7;
      }
    }
  }
  .file-shadow {
    background-color: rgba(0, 0, 0, 1);
    opacity: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    z-index: 1;
    .preview-icon {
      color: #fff;
      z-index: 10;
      cursor: pointer;
    }
  }
  .file-shadow-false {
    background-color: transparent;
    opacity: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    z-index: 1;
    // .preview-icon {
    //   color: #fff;
    //   z-index: 10;
    //   cursor: pointer;
    // }
  }

  .upload-rules {
    color: red;
    font-size: 12px;
  }
}

.custom-btn {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}
.preImg {
  display: flex;
  flex-wrap: wrap;
  figure {
    position: relative;
    width: 146px;
    height: 146px;
    overflow: hidden;
    border-radius: 8px;
    margin: 10px 10px 10px 0;
    cursor: pointer;
    &:first-child {
      margin-left: 10px;
    }
    img {
      width: 100%;
      height: 100%;
      display: block;
    }
    &:hover {
      color: #fff;
    }
    .pop {
      width: 100%;
      height: 100%;
      position: absolute;
      left: 0;
      top: 0;
      display: flex;
      justify-content: center;
      align-items: center;
      &:hover {
        background-color: rgba(0, 0, 0, 0.475);
        .closeIcon {
          display: block;
        }
        .preIcon {
          display: block;
        }
      }
      .closeIcon {
        display: none;
        width: 20px;
        height: 20px;
        margin-right: 10px;
      }
      .preIcon {
        display: none;
        width: 20px;
        height: 20px;
        margin-left: 10px;
      }
    }
  }
}
.el-button + .el-button {
  margin-left: 0px;
  margin-top: 20px;
}
</style>
